home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility1 / gs261src.zip / ZCHAR.C < prev    next >
C/C++ Source or Header  |  1993-05-27  |  14KB  |  481 lines

  1. /* Copyright (C) 1989, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* zchar.c */
  20. /* Character operators for Ghostscript */
  21. #include "ghost.h"
  22. #include "errors.h"
  23. #include "oper.h"
  24. #include "gxarith.h"
  25. #include "gxfixed.h"            /* for gstype1.h */
  26. #include "gxmatrix.h"            /* for font.h */
  27. #include "gschar.h"
  28. #include "gxdevice.h"            /* for gxfont.h */
  29. #include "gxfont.h"
  30. #include "gxtype1.h"            /* should be gstype1.h, but */
  31.                     /* we need sizeof(gs_type1_state) */
  32.                     /* so we can use stack allocation */
  33. #include "gzpath.h"            /* for type1addpath: see below */
  34. #include "gzstate.h"
  35. #include "alloc.h"
  36. #include "dict.h"
  37. #include "font.h"
  38. #include "estack.h"
  39. #include "ilevel.h"
  40. #include "iname.h"
  41. #include "state.h"
  42. #include "store.h"
  43.  
  44. /* Procedures exported for zchar2.c; */
  45. /* these are also internal forward references. */
  46. int op_show_setup(P2(os_ptr, int /*bool*/));
  47. int op_show_continue(P1(os_ptr));
  48. int op_show_continue_dispatch(P2(os_ptr, int));
  49. gs_show_enum *op_show_find(P0());
  50. /* gs_show_enum *op_show_senum(P0()); */
  51. /* ref *op_show_psslot(P0()); */
  52. int op_show_cleanup(P1(os_ptr));
  53. void op_show_free(P0());
  54.  
  55. /* All the character rendering operators use the execution stack */
  56. /* for loop control -- see estack.h for details. */
  57. /* The information pushed by these operators is as follows: */
  58. /*    the enumerator (t_string, but points to a gs_show_enum); */
  59. /*    a slot for the procedure for kshow or the stream for [x][y]show */
  60. /*        (t_string, but points to a stream), unused otherwise; */
  61. /*    the procedure to be called at the end of the enumeration */
  62. /*        (t_operator, but called directly, not by the interpreter); */
  63. /*    the usual e-stack mark (t_null). */
  64. #define snumpush 4
  65. #define senum (gs_show_enum *)(esp->value.bytes)
  66. #define sslot esp[-1]
  67. #define seproc esp[-2]
  68.  
  69. /* Forward references */
  70. private int show_enum_setup(P2(os_ptr, op_proc_p));
  71. private int finish_show(P1(os_ptr));
  72. private int finish_stringwidth(P1(os_ptr));
  73.  
  74. /* <string> show - */
  75. int
  76. zshow(register os_ptr op)
  77. {    int code = op_show_setup(op, 1);
  78.     if ( code < 0 ) return code;
  79.     if ( (code = gs_show_n_init(senum, igs, (char *)op->value.bytes, r_size(op))) < 0 )
  80.        {    op_show_free();
  81.         return code;
  82.        }
  83.     pop(1);  op--;
  84.     return op_show_continue(op);
  85. }
  86.  
  87. /* <ax> <ay> <string> ashow - */
  88. int
  89. zashow(register os_ptr op)
  90. {    int code;
  91.     float axy[2];
  92.     if (    (code = num_params(op - 1, 2, axy)) < 0 ||
  93.         (code = op_show_setup(op, 1)) < 0
  94.        )
  95.         return code;
  96.     if ( (code = gs_ashow_n_init(senum, igs, axy[0], axy[1], (char *)op->value.bytes, r_size(op))) < 0 )
  97.        {    op_show_free();
  98.         return code;
  99.        }
  100.     pop(3);  op -= 3;
  101.     return op_show_continue(op);
  102. }
  103.  
  104. /* <cx> <cy> <char> <string> widthshow - */
  105. int
  106. zwidthshow(register os_ptr op)
  107. {    int code;
  108.     float cxy[2];
  109.     check_type(op[-1], t_integer);
  110.     if ( (gs_char)(op[-1].value.intval) != op[-1].value.intval )
  111.         return_error(e_rangecheck);
  112.     if (    (code = num_params(op - 2, 2, cxy)) < 0 ||
  113.         (code = op_show_setup(op, 1)) < 0
  114.        )
  115.         return code;
  116.     if ( (code = gs_widthshow_n_init(senum, igs, cxy[0], cxy[1],
  117.                      (gs_char)op[-1].value.intval,
  118.                      (char *)op->value.bytes,
  119.                      r_size(op))) < 0 )
  120.        {    op_show_free();
  121.         return code;
  122.        }
  123.     pop(4);  op -= 4;
  124.     return op_show_continue(op);
  125. }
  126.  
  127. /* <cx> <cy> <char> <ax> <ay> <string> awidthshow - */
  128. int
  129. zawidthshow(register os_ptr op)
  130. {    int code;
  131.     float cxy[2], axy[2];
  132.     check_type(op[-3], t_integer);
  133.     if ( (gs_char)(op[-3].value.intval) != op[-3].value.intval )
  134.         return_error(e_rangecheck);
  135.     if (    (code = num_params(op - 4, 2, cxy)) < 0 ||
  136.         (code = num_params(op - 1, 2, axy)) < 0 ||
  137.         (code = op_show_setup(op, 1)) < 0
  138.        )
  139.         return code;
  140.     if ( (code = gs_awidthshow_n_init(senum, igs, cxy[0], cxy[1],
  141.                       (gs_char)op[-3].value.intval,
  142.                       axy[0], axy[1],
  143.                       (char *)op->value.bytes,
  144.                       r_size(op))) < 0 )
  145.        {    op_show_free();
  146.         return code;
  147.        }
  148.     pop(6);  op -= 6;
  149.     return op_show_continue(op);
  150. }
  151.  
  152. /* <proc> <string> kshow - */
  153. int
  154. zkshow(register os_ptr op)
  155. {    int code;
  156.     check_proc(op[-1]);
  157.     if ( (code = op_show_setup(op, 1)) < 0 ) return code;
  158.     if ( (code = gs_kshow_n_init(senum, igs, (char *)op->value.bytes, r_size(op))) < 0 )
  159.        {    op_show_free();
  160.         return code;
  161.        }
  162.     sslot = op[-1];        /* save kerning proc */
  163.     pop(2);  op -= 2;
  164.     return op_show_continue(op);
  165. }
  166.  
  167. /* Common finish procedure for all show operations. */
  168. /* Doesn't have to do anything. */
  169. private int
  170. finish_show(os_ptr op)
  171. {    return 0;
  172. }
  173.  
  174. /* <string> stringwidth <wx> <wy> */
  175. int
  176. zstringwidth(register os_ptr op)
  177. {    int code;
  178.     check_read_type(*op, t_string);
  179.     code = show_enum_setup(op, finish_stringwidth);
  180.     if ( code < 0 ) return code;
  181.     if ( (code = gs_stringwidth_n_init(senum, igs, (char *)op->value.bytes, r_size(op))) < 0 )
  182.        {    op_show_free();
  183.         return code;
  184.        }
  185.     pop(1);  op--;
  186.     return op_show_continue(op);
  187. }
  188. /* Finishing procedure for stringwidth. */
  189. /* Pushes the accumulated width. */
  190. private int
  191. finish_stringwidth(register os_ptr op)
  192. {    gs_point width;
  193.     gs_show_width(senum, &width);
  194.     push(2);
  195.     make_real(op - 1, width.x);
  196.     make_real(op, width.y);
  197.     return 0;
  198. }
  199.  
  200. /* <string> <outline_bool> charpath - */
  201. int
  202. zcharpath(register os_ptr op)
  203. {    int code;
  204.     check_type(*op, t_boolean);
  205.     code = op_show_setup(op - 1, 1);
  206.     if ( code < 0 ) return code;
  207.     if ( (code = gs_charpath_n_init(senum, igs, (char *)op[-1].value.bytes, r_size(op - 1), op->value.index)) < 0 )
  208.        {    op_show_free();
  209.         return code;
  210.        }
  211.     pop(2);  op -= 2;
  212.     return op_show_continue(op);
  213. }
  214.  
  215. /* <wx> <wy> <llx> <lly> <urx> <ury> setcachedevice - */
  216. int
  217. zsetcachedevice(register os_ptr op)
  218. {    float wbox[6];
  219.     gs_show_enum *penum = op_show_find();
  220.     int code = num_params(op, 6, wbox);
  221.     if ( penum == 0 )
  222.         return_error(e_undefined);
  223.     if ( code < 0 )
  224.         return code;
  225.     if ( (code = gs_setcachedevice(penum, igs, wbox[0], wbox[1], wbox[2], wbox[3], wbox[4], wbox[5])) < 0 )
  226.         return code;
  227.     pop(6);
  228.     return 0;
  229. }
  230.  
  231. /* <wx> <wy> setcharwidth - */
  232. int
  233. zsetcharwidth(register os_ptr op)
  234. {    float width[2];
  235.     gs_show_enum *penum = op_show_find();
  236.     int code = num_params(op, 2, width);
  237.     if ( penum == 0 )
  238.         return_error(e_undefined);
  239.     if (    code < 0 || 
  240.         (code = gs_setcharwidth(penum, igs, width[0], width[1])) < 0
  241.        )
  242.         return code;
  243.     pop(2);
  244.     return 0;
  245. }
  246.  
  247. /* <string> .type1addpath - */
  248. /* <string> <lsbx> <lsby> .type1addpath - */
  249. typedef struct {
  250.     gs_font *pfont;
  251.     fixed *osptr;            /* fake interpreter operand stack */
  252.     fixed ostack[2];
  253. } z1_data;
  254. int
  255. ztype1addpath(register os_ptr op)
  256. {    int code = 0;
  257.     int value;
  258.     gs_show_enum *penum = op_show_find();
  259.     gs_font *pfont = gs_currentfont(igs);
  260.     font_data *pfdata = (font_data *)pfont->client_data;
  261.     gs_type1_state is;        /* stack allocate to avoid sandbars */
  262.     gs_type1_state *pis = &is;
  263.     float sbxy[2];
  264.     gs_point sbpt;
  265.     gs_point *psbpt = 0;
  266.     os_ptr opc = op;
  267.     gs_type1_data tdata;
  268.     z1_data zdata;
  269.     const byte *charstring;
  270.     if ( penum == 0 )
  271.         return_error(e_undefined);
  272.     if ( num_params(op, 2, sbxy) >= 0 )
  273.     {    sbpt.x = sbxy[0];
  274.         sbpt.y = sbxy[1];
  275.         psbpt = &sbpt;
  276.         opc -= 2;
  277.     }
  278.     check_type(*opc, t_string);
  279.     tdata = pfont->data.base.type1_data;
  280.     zdata.pfont = pfont;
  281.     zdata.osptr = zdata.ostack;
  282.     tdata.proc_data = (char *)&zdata;
  283.     if ( r_size(opc) <= tdata.lenIV )
  284.        {    /* String is empty, or too short.  Just ignore it. */
  285.         goto ret;
  286.        }
  287.     code = gs_type1_init(pis, penum,
  288.                  gs_show_in_charpath(penum), tdata.PaintType,
  289.                  &tdata);
  290.     if ( code < 0 ) return code;
  291.     charstring = opc->value.const_bytes;
  292. more:    code = gs_type1_interpret(pis, charstring, psbpt, &value);
  293.     charstring = 0;
  294.     switch ( code )
  295.        {
  296.     case type1_result_seac:
  297.        {    ref *pcstr;
  298.         ref enc_entry;
  299.         code = array_get(&StandardEncoding, (long)value, &enc_entry);
  300.         if ( code < 0 ) return code;
  301.         if ( dict_find(&pfdata->CharStrings,
  302.                    &enc_entry, &pcstr) <= 0 )
  303.             return_error(e_undefined);
  304.         if ( !r_has_type(pcstr, t_string) )
  305.             return_error(e_invalidfont);
  306.         charstring = pcstr->value.const_bytes;
  307.        }    goto more;
  308.     case type1_result_callothersubr:
  309.         /* The Type 1 interpreter handles all known othersubrs, */
  310.         /* so this must be an unknown one. */
  311.         code = e_rangecheck;
  312.         break;
  313.        }
  314.     if ( code < 0 ) return code;
  315. ret:    pop((psbpt == 0 ? 1 : 3));
  316.     return code;
  317. }
  318.  
  319. /* ------ Auxiliary procedures for type 1 fonts ------ */
  320.  
  321. int
  322. z1_subr_proc(gs_type1_data *pdata, int index, const byte **pstr)
  323. {    gs_font *pfont = ((z1_data *)(pdata->proc_data))->pfont;
  324.     font_data *pfdata = (font_data *)(pfont->client_data);
  325.     ref *psubr;
  326.     if ( index < 0 || index >= r_size(&pfdata->Subrs) )
  327.         return_error(e_rangecheck);
  328.     psubr = pfdata->Subrs.value.refs + index;
  329.     check_type(*psubr, t_string);
  330.     *pstr = psubr->value.bytes;
  331.     return 0;
  332. }
  333.  
  334. int
  335. z1_pop_proc(gs_type1_data *pdata, fixed *pf)
  336. {    *pf = *--(((z1_data *)(pdata->proc_data))->osptr);
  337.     return 0;
  338. }
  339.  
  340. /* ------ Initialization procedure ------ */
  341.  
  342. op_def zchar_op_defs[] = {
  343.     {"3ashow", zashow},
  344.     {"6awidthshow", zawidthshow},
  345.     {"2charpath", zcharpath},
  346.     {"2kshow", zkshow},
  347.     {"6setcachedevice", zsetcachedevice},
  348.     {"2setcharwidth", zsetcharwidth},
  349.     {"1show", zshow},
  350.     {"1stringwidth", zstringwidth},
  351.     {"1.type1addpath", ztype1addpath},
  352.     {"4widthshow", zwidthshow},
  353.         /* Internal operators */
  354.     {"0%finish_show", finish_show},
  355.     {"0%finish_stringwidth", finish_stringwidth},
  356.     {"0%op_show_continue", op_show_continue},
  357.     op_def_end(0)
  358. };
  359.  
  360. /* ------ Subroutines ------ */
  361.  
  362. /* Most of these are exported for zchar2.c. */ 
  363.  
  364. /* Set up for a show operator.  If check_string is true, */
  365. /* the top stack element must be the string to be scanned. */
  366. /* The caller has already done all other argument checking. */
  367. int
  368. op_show_setup(os_ptr op, int check_string)
  369. {    if ( check_string )
  370.     {    check_read_type(*op, t_string);
  371.     }
  372.     return show_enum_setup(op, finish_show);
  373. }
  374. private int
  375. show_enum_setup(os_ptr op, op_proc_p endproc /* end procedure */)
  376. {    gs_show_enum *penum;
  377.     check_estack(snumpush + 2);
  378.     if ( (penum = (gs_show_enum *)alloc(1, gs_show_enum_sizeof, "setup_show")) == 0 )
  379.         return_error(e_VMerror);
  380.     mark_estack(es_show, op_show_cleanup);
  381.     push_op_estack(endproc);
  382.     ++esp;
  383.     make_null(esp);        /* reserve sslot */
  384.     ++esp;
  385.     make_tasv(esp, t_string, 0, gs_show_enum_sizeof, bytes, (byte *)penum);
  386.     return o_push_estack;
  387. }
  388.  
  389. /* Continuation operator for character rendering. */
  390. int
  391. op_show_continue(os_ptr op)
  392. {    return op_show_continue_dispatch(op, gs_show_next(senum));
  393. }
  394. int
  395. op_show_continue_dispatch(register os_ptr op, int code)
  396. {    gs_show_enum *penum = senum;
  397.     switch ( code )
  398.        {
  399.     case 0:                /* all done */
  400.         code = (*real_opproc(&seproc))(op);
  401.         op_show_free();
  402.         return (code >= 0 ? o_pop_estack : code);
  403.     case gs_show_kern:
  404.        {    ref *pslot = &sslot;
  405.         push(2);
  406.         make_int(op - 1, gs_kshow_previous_char(penum));
  407.         make_int(op, gs_kshow_next_char(penum));
  408.         push_op_estack(op_show_continue);        /* continue after kerning */
  409.         *++esp = *pslot;    /* kerning procedure */
  410.        }
  411.         return o_push_estack;
  412.     case gs_show_render:
  413.        {    font_data *pfdata = (font_data *)gs_currentfont(igs)->client_data;
  414.         push(2);
  415.         op[-1] = pfdata->dict;    /* push the font */
  416.         if ( level2_enabled && !r_has_type(&pfdata->BuildGlyph, t_null) )
  417.         {    /* Use BuildGlyph. */
  418.             gs_glyph glyph = gs_show_current_glyph(penum);
  419.             if ( glyph == gs_no_glyph )
  420.                 goto err;    /* not possible (!) */
  421.             name_index_ref(glyph, op);
  422.             esp[2] = pfdata->BuildGlyph;
  423.         }
  424.         else
  425.         {    /* Use BuildChar. */
  426.             gs_char chr = gs_show_current_char(penum);
  427.             if ( chr == gs_no_char )
  428.                 goto err;    /* only possible for glyphshow */
  429.             make_int(op, chr);
  430.             esp[2] = pfdata->BuildChar;
  431.         }
  432.         push_op_estack(op_show_continue);
  433.         ++esp;        /* skip BuildChar or BuildGlyph proc */
  434.        }
  435.         return o_push_estack;
  436.     default:            /* error */
  437. err:        op_show_free();
  438.         return (code < 0 ? code : e_invalidfont);
  439.        }
  440. }
  441.  
  442. /* Find the current show enumerator on the e-stack. */
  443. gs_show_enum *
  444. op_show_find(void)
  445. {    es_ptr ep = esp;
  446.     while ( !(r_is_estack_mark(ep) && estack_mark_index(ep) == es_show) )
  447.        {    if ( --ep < esbot ) return 0;    /* no mark */
  448.        }
  449.     return (gs_show_enum *)ep[snumpush - 1].value.bytes;
  450. }
  451.  
  452. /* Return the current enumerator for the continuation procedure. */
  453. gs_show_enum *
  454. op_show_senum(void)
  455. {    return senum;
  456. }
  457.  
  458. /* Return the address of the current procedure slot ditto. */
  459. ref *
  460. op_show_psslot(void)
  461. {    return &sslot;
  462. }
  463.  
  464. /* Discard the show record (after an error, or at the end). */
  465. int
  466. op_show_cleanup(os_ptr op)
  467. {    register es_ptr ep = esp + snumpush;
  468. #define esp ep        /* for senum, sslot */
  469.     if ( r_has_type(&sslot, t_string) )
  470.         alloc_free((char *)sslot.value.bytes, 1, r_size(&sslot),
  471.                "free_show(stream)");
  472.     alloc_free((char *)senum, 1, gs_show_enum_sizeof, "free_show(enum)");
  473. #undef esp
  474.     return 0;
  475. }
  476. void
  477. op_show_free(void)
  478. {    esp -= snumpush;
  479.     op_show_cleanup(osp);
  480. }
  481.